/*************************************************************************
	> File Name: acquisitor.cpp
	> Author: xuwenlong
	> Mail: myxuan475@126.com 
	> Created Time: 2018年02月02日 星期五 14时22分15秒
 ************************************************************************/

#include<stdio.h>
#include <dlfcn.h>
#include <time.h>
#include <utils/sqlite.h>
#include <dbms/acquire.h>
#include <dbms/exprs.h>
#include <algorithm>
#include <dbms/status.h>
#include "acqdata.h"
#include "acquisitor.h"
#include "acquisition.h"
#include <devices/devices.h>

Acquisitor::Acquisitor(const deviceinfo_t& devinfo):
    m_idevinfo(devinfo),
    m_bStop(TRUE),
    m_bStat(FALSE) {
//    m_idevinfo.trans.sample = 1;//test

    updateAquireData(m_idevinfo);
}

Acquisitor::~Acquisitor()
{
    m_bStop = TRUE;
    m_bStat = FALSE;
}

void Acquisitor::DoRun(tConnection connector, const time_t &acqtime)
{
    /* 获取指令 */
    status sta(m_idevinfo.id);
    /*
     * 清除状态
     */

    if (!connector.valid()) {
        m_bStat = false;
        sta.update_status(m_bStat);
        return commitError(GetError(DAS_FAILDCONNECTION));
    }

    if (isStop()) {
        return;
    }
    Run(connector,acqtime,listAcquire);

    sta.update_status(m_bStat);

    //json 格式
    Json::Value record;
    for (vector<AcqItem>::iterator iter = listAcquire.begin();
         iter != listAcquire.end();iter++) {
        AcqItem &acqItem = (AcqItem &)*iter;

        Json::Value acq;
        acq["acq"] = acquire::idToStr(acqItem.GetId());
        acq["name"] = acqItem.GetName();
        acq["value"] = acqItem.ToJson();
        record.append(acq);
    }
    sta.set_acqdata(record.toStyledString());
}

U16 Acquisitor::acquireDevice(
        tConnection connector,
        tDataItem &acqItem,OpValue &result,
        vector<CmdValue> *listResult)
{
    OpValue opValue;
    U16 err = 0;

    if (!connector.valid()|| !acqItem.valid()) {
        return DAS_FAILDCONNECTION;
    }

    opValue = acqItem->GenerateCmd();
    if (opValue.IsEmpty()) {
        LOG_ERR("generate cmd error");
        return DAS_INVALIDPARAMETER;
    }

    //采集
    /*int err = 0;*///4:采集失败，5：解析失败
    for (int i = 0;i < 2;i++) {
        OpValue tmpValue = opValue;
        err = 0;

        acqItem->ResetCmd();
        while (!tmpValue.IsEmpty()) {
            CmdValue cmdValue = tmpValue.GenCmd();
            U8 buffer[512];
            S32 byte = 0;

            if (m_bStop)
                return DAS_FORCESET;
            if (!connector->AtomGetInstruction(
                        m_idevinfo.trans ,
                        cmdValue.Cmd(),cmdValue.Length(),
                        buffer,byte)) {
                err = DAS_ACQUIREFAILED;
                break;
            }
            CmdValue recv;

            recv = CmdValue(buffer,byte);

            if (RECV_COMPLETE != acqItem->ParseRecvCmd(recv)) {
                err = DAS_PARSEFAILED;
                break;
            }
            //记录之前打采集

            if (listResult) {
                listResult->push_back(recv);
            }
            tmpValue = acqItem->GenerateNext();
        }

        if (err != 0)
            continue;
        result = acqItem->Result();
        return err;
    }
    return err;
}

BOOL Acquisitor::IsEqualId(S32 id)
{
    return id==m_idevinfo.id;
}

S32 Acquisitor::DevId()
{
    return m_idevinfo.id;
}

OpValue Acquisitor::indicateDevice(
        tConnection connector,
        const string &itemId,
        const vector<OpValue> &params)
{
    tDataItem item;
    OpValue result;

    if (!connector.valid())
        return OpValue::Null();

    item = GetItemByDot(itemId);
    if (!item.valid())
        return OpValue::Null();
    if (!params.empty()) {
        item = new DataItem(*item);
        item->CalcParams(params);
    }
    acquireDevice(connector,item,result,NULL);

    return result;
}

OpValue Acquisitor::indicateDevice(
        tConnection connector,
        S32 itemId, const vector<OpValue> &params)
{
    tDataItem item;
    OpValue result;

    if (!connector.valid())
        return OpValue::Null();

    item = GetItemById(itemId);
    if (!item.valid())
        return OpValue::Null();
    if (!params.empty()) {
        item = new DataItem(*item);
        item->CalcParams(params);
    }
    acquireDevice(connector,item,result,NULL);

    return result;
}

OpValue Acquisitor::indicateDevice(
        tConnection connector,
        const string &itemId, const OpValue &param)
{
    if (param.IsEmpty())
        return indicateDevice(connector,itemId,vector<OpValue>());
    else {
        vector<OpValue> list;
        list.push_back(param);
        return indicateDevice(connector,itemId,list);
    }
}

OpValue Acquisitor::indicateDevice(
        tConnection connector,
        S32 itemId, const OpValue &param)
{
    if (param.IsEmpty())
        return indicateDevice(connector,itemId,vector<OpValue>());
    else {
        vector<OpValue> list;
        list.push_back(param);
        return indicateDevice(connector,itemId,list);
    }
}

//U16 Acquisitor::acquireDevice(
//        tConnection connector,U16 index,
//        U16 len,vector<OpValue> &out)
//{
//    tDataItem item;

//    if (m_bStat) {
//        Devices dev;
//        Json::Value jrt = dev.getAcquireData(m_idevinfo.id);

//        for (int i = 0;i < len;i++) {
//            item = GetItemByIndex(index+i);
//            if (!item.valid()) {
//                return DAS_NOITEM;
//            }

//            OpValue value;
//            for (int i = 0;i < jrt.size();i++) {
//                const Json::Value &iv = jrt[i];
//                if (!iv.isMember("acq"))
//                    continue;
//                string stracq = iv["acq"].asString();
//                if (item->GetDot() == stracq) {
//                    if (!iv.isMember("value"))
//                        return DAS_NOITEM;
//                    TYPE_DEFINE type = item->DataType();
//                    if (type == TYPE_F32 || type == TYPE_F64)
//                        value = iv["value"].asFloat();
//                    else
//                        value = (S32)iv["value"].asFloat();
//                    break;
//                }
//            }
//            if (value.IsEmpty())
//                return DAS_NOITEM;
//            out.push_back(value);
//        }
//        return 0;
//    }
//    else {
//        for (int i = 0;i < len;i++) {
//            U16 err;
//            item = GetItemByIndex(index+i);
//            if (!item.valid()) {
//                return DAS_NOITEM;
//            }

//            OpValue value;
//            err = acquireDevice(connector,item,value,NULL);
//            if (!err)
//                return err;
//            out.push_back(value);
//        }
//        return 0;
//    }
//}

Json::Value Acquisitor::acquireList()
{
    Json::Value illustrate;

    for (int i = 0;i < m_listDataItems.size();i++) {
        tDataItem &item = m_listDataItems.at(i);
        if (item->GetItemId()/10000 != 3)
            continue;
        Json::Value ill;
        ill["devId"] = m_idevinfo.id;
        ill["acqId"] = i+1;
        ill["name"] = item->GetName();
        ill["reglen"] = 4;
        ill["type"] = dateType(item);
        illustrate.append(ill);
    }
    return illustrate;
}

BOOL Acquisitor::OnReceiveJson(
        S32 index,
        DAS_RESULT result,
        const string &method,
        const Json::Value &json)
{
    return TRUE;
}

bool Acquisitor::acquireStatus()
{
    return m_bStat;
}

bool Acquisitor::powerStatus(tConnection &connector)
{
    status sta(m_idevinfo.id);
    //开关状态
    bool bPower = false;//sta.ionoff();
    OpValue power = indicateDevice(connector,10006);

    if (!power.IsEmpty()) {
        bPower = (bool)(power.Integer() != 0);
    }

    sta.update_onoff(bPower);
    return bPower;
}

BOOL Acquisitor::updateAquireData(const deviceinfo_t& devinfo)
{
    AutoLock aulock(m_iLock);
    m_listDataItems.clear();
    acquire aq(devinfo.model_id);

    aq.FetchItems();

    vector<acquire::acquiredata>& list=aq.getAcqParams();

    for (int i = 0;i < list.size();i++) {
        tDataItem item = new DataItem(devinfo.dev_id,devinfo.model_id);
        acquire::acquiredata& data = list.at(i);
        item->SetItemId(data.itemId);
        item->SetDot(data.itemDot);
        item->SetName(data.itemName);
        item->SetRegLength(data.reglen);
        item->ParseDataExpr(data.dataexpr,data.fRate);
        item->ParseParams(data.listparams);

        bool insert = false;
        for (vector<tDataItem>::iterator iter = m_listDataItems.begin();
             iter != m_listDataItems.end();iter++) {
            const tDataItem &it = *iter;
            if (item->GetItemId() <= it->GetItemId()) {
                continue;
            }
            m_listDataItems.insert(iter,item);
            insert = true;
            break;
        }
        if (!insert)
            m_listDataItems.push_back(item);


    }
}

void Acquisitor::startAcquire()
{
    m_bStop = false;
}

void Acquisitor::stopAcquire()
{
    m_bStop = true;
}

bool Acquisitor::isStop()
{
    return m_bStop;
}

int Acquisitor::acqCount()
{
    return m_listDataItems.size();
}

void Acquisitor::updateAcquisitor(const deviceinfo_t &devinfo)
{
    m_idevinfo = devinfo;
    updateAquireData(devinfo);
}

void Acquisitor::clearData()
{
}

S32 Acquisitor::sendRpc(int index,
        const string &method,
        const Json::Value &params)
{
    if (!GetMsgStatus(DAS_REGISTERACQUISITOR,index))
        return -1;
    AcquisitionManager *acqMgr = (AcquisitionManager*)GetTask(DAS_ACQUISITOR,index);
    return acqMgr->RpcInterface()->SendJsonRpc(
                this,method,params);
}

void Acquisitor::commitError(const string &err)
{
    Json::Value params;
    params["id"] = m_idevinfo.id;
    params["devId"] = m_idevinfo.dev_id.c_str();
    params["error"] = err;
    for (int i = 0;i < TotalCenter();i++ ) {
        sendRpc(i,"commitError",params);
    }
}

string Acquisitor::dateType(tDataItem &item)
{
    switch(item->DataType())
    {
    case TYPE_NONE:
        return "未知类型";
    case TYPE_U8:
    case TYPE_S8:
    case TYPE_U16:
    case TYPE_S16:
    case TYPE_U32:
    case TYPE_S32:
    case TYPE_U64:
    case TYPE_S64:
        return "16进制整型";
    case TYPE_F32:
    case TYPE_F64:
        return "IEEE 754 浮点型";
    case TYPE_CMD:
        return "16进制类型";
    }
}

tDataItem Acquisitor::GetItemByIndex(S32 index)
{
    AutoLock aulock(m_iLock);

    //查找之前打可采集点
    if (index >= m_listDataItems.size())
        return NULL;
    return m_listDataItems.at(index);
}

tDataItem Acquisitor::GetItemById(S32 itemId)
{
    AutoLock aulock(m_iLock);

    //查找之前打可采集点
    for (int i = 0;i < m_listDataItems.size();i++) {
        tDataItem& dateItem = m_listDataItems.at(i);

        if (dateItem->GetItemId() == itemId) {
            return dateItem;
        }
    }
    return NULL;
}

tDataItem Acquisitor::GetAcqItem(tDataItem item,U8 flag)
{
    AutoLock aulock(m_iLock);
    int i = 0;

    //查找之前打可采集点
    for (;i < m_listDataItems.size();i++) {
        tDataItem dateItem = m_listDataItems.at(i);
        U8 uf = (0x01<<(dateItem->GetItemId()/10000));
        if (!(uf & flag))
            continue;
        if (item.valid()) {
            if (dateItem->GetItemId() == item->GetItemId()) {
                i++;
                break;
            }
        }
        else {
            return dateItem;
        }
    }

    //查找后续采集点
    for (;i < m_listDataItems.size();i++) {
        tDataItem& dateItem = m_listDataItems.at(i);
        U8 ug = ((0x01<<(dateItem->GetItemId()/10000)));
        if ((ug & flag))
            return dateItem;
    }
    return NULL;
}

tDataItem Acquisitor::GetItemByDot(const string &dot)
{
    AutoLock aulock(m_iLock);

    //查找之前打可采集点
    for (int i = 0;i < m_listDataItems.size();i++) {
        tDataItem dateItem = m_listDataItems.at(i);

        if (dateItem->GetDot() == dot) {
            return dateItem;
        }
    }
    return NULL;
}


